package com.tianji.learning.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.api.cache.CategoryCache;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.client.search.SearchClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.course.CataSimpleInfoDTO;
import com.tianji.api.dto.course.CatalogueDTO;
import com.tianji.api.dto.course.CourseSimpleInfoDTO;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.utils.AssertUtils;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.StringUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.entity.InteractionQuestion;
import com.tianji.learning.entity.InteractionReply;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.pojo.QuestionAdminPageQuery;
import com.tianji.learning.pojo.QuestionFormDTO;
import com.tianji.learning.pojo.QuestionPageQuery;
import com.tianji.learning.pojo.QuestionVO;
import com.tianji.learning.service.IInteractionQuestionService;
import com.tianji.learning.service.IInteractionReplyService;
import com.tianji.learning.vo.QuestionAdminVO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 互动提问的问题表 服务实现类
 * </p>
 *
 * @author xjs
 */
@Service
@RequiredArgsConstructor
public class InteractionQuestionServiceImpl extends ServiceImpl<InteractionQuestionMapper, InteractionQuestion> implements IInteractionQuestionService {


    private final IInteractionReplyService replyService;
    private final UserClient userClient;
    private final SearchClient searchClient;
    private final CourseClient courseClient;
    private final CategoryCache categoryCache;
    private final CatalogueClient catalogueClient;

    @Override
    public PageDTO<QuestionAdminVO> adminPageQuery(QuestionAdminPageQuery query) {
        // 把课程名转化成课程的id列表
        List<Long> courseIds = null;
        if(StringUtils.isNotBlank(query.getCourseName())){
            courseIds = searchClient.queryCoursesIdByName(query.getCourseName());
            if(CollectionUtils.isEmpty(courseIds)){
                return PageDTO.empty(new Page<>(query.getPageNo(), query.getPageSize()));
            }
        }
        // 设置分页条件
        Page<InteractionQuestion> ipage = query.toMpPageDefaultSortByCreateTimeDesc();
        // 设置查询条件
        LambdaQueryWrapper<InteractionQuestion> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(query.getStatus()!=null, InteractionQuestion::getStatus, query.getStatus())
                .gt(query.getBeginTime()!=null,InteractionQuestion::getCreateTime, query.getBeginTime())
                .lt(query.getEndTime()!=null,InteractionQuestion::getCreateTime, query.getEndTime())
                .in(!CollectionUtils.isEmpty(courseIds), InteractionQuestion::getCourseId, courseIds);
        // 分页查询
        Page<InteractionQuestion> page = this.page(ipage, queryWrapper);
        List<InteractionQuestion> questions = page.getRecords();
        if(CollectionUtils.isEmpty(questions)){
            return PageDTO.empty(ipage);
        }
        // 批量查询用户信息
        Set<Long> userIds = questions.stream().map(InteractionQuestion::getUserId).collect(Collectors.toSet());
        List<UserDTO> userList = userClient.queryUserByIds(userIds);
        AssertUtils.isNotNull(userList, "用户不能为空");
        Map<Long, UserDTO> userMap = userList.stream().collect(Collectors.toMap(UserDTO::getId, dto -> dto));

        // 批量查询课程信息
        courseIds = questions.stream().map(InteractionQuestion::getCourseId).distinct().collect(Collectors.toList());
        List<CourseSimpleInfoDTO> courseList = courseClient.getSimpleInfoList(courseIds);
        AssertUtils.isNotNull(userList, "课程不能为空");
        Map<Long, CourseSimpleInfoDTO> courseMap = courseList.stream().collect(Collectors.toMap(CourseSimpleInfoDTO::getId, c -> c));

        // 批量查询章节信息
        Set<Long> chapterIds = questions.stream().map(InteractionQuestion::getChapterId).collect(Collectors.toSet());
        Set<Long> sectionsIds =questions.stream().map(InteractionQuestion::getSectionId).collect(Collectors.toSet());
        Set<Long> catalogIds = new HashSet<>();
        catalogIds.addAll(chapterIds);
        catalogIds.addAll(sectionsIds);
        List<CataSimpleInfoDTO> catalogueList = catalogueClient.batchQueryCatalogue(catalogIds);
        AssertUtils.isNotNull(catalogueList, "章节不能为空");
        Map<Long, CataSimpleInfoDTO> catalogMap = catalogueList.stream().collect(Collectors.toMap(CataSimpleInfoDTO::getId, c -> c));

        // 把数据库的Question转化成前端展示需要的VO
        List<QuestionAdminVO> voList = new ArrayList<>();
        for (InteractionQuestion question : questions) {

            //属性copy
            QuestionAdminVO vo = BeanUtils.copyBean(question, QuestionAdminVO.class);

//            // feign->userId查user
//            UserDTO user = userClient.queryUserById(question.getUserId());
            UserDTO user = userMap.get(question.getUserId());
            vo.setUserName(user==null?null:user.getName());

//            // feign->courseId查courseName
//            CourseFullInfoDTO course = courseClient.getCourseInfoById(question.getCourseId(), true, false);
            CourseSimpleInfoDTO course = courseMap.get(question.getCourseId());
            AssertUtils.isNotNull(course, "课程不能为空");
            vo.setCourseName(course.getName());

             // chapterId查chapterName;
//           List<CatalogueDTO> chapters = course.getChapters();
//           CatalogueDTO chapter = getCatalogue(chapters,question.getChapterId());
            CataSimpleInfoDTO chapter = catalogMap.get(question.getChapterId());
            AssertUtils.isNotNull(chapter, "章不能为空");
            vo.setChapterName(chapter.getName());

              // sectionId查sectionName
//           List<CatalogueDTO> sections = chapter.getSections();
//           CatalogueDTO section = getCatalogue(sections, question.getSectionId());
            CataSimpleInfoDTO section = catalogMap.get(question.getSectionId());
            AssertUtils.isNotNull(section, "节不能为空");
            vo.setSectionName(section.getName());

            // feign->courseId查分类信息
            Long firstCateId = course.getFirstCateId();
            Long secondCateId = course.getSecondCateId();
            Long thirdCateId = course.getThirdCateId();
            String categoryNames = categoryCache.getCategoryNames(Arrays.asList(firstCateId, secondCateId, thirdCateId));
            vo.setCategoryName(categoryNames);

            // 添加到结果集
            voList.add(vo);
        }
        return PageDTO.of(ipage, voList);
    }

    private CatalogueDTO getCatalogue(List<CatalogueDTO> sections, Long sectionId) {
        if(CollectionUtils.isEmpty(sections)){
            return null;
        }
        Optional<CatalogueDTO> any = sections.stream().filter(s -> Objects.equals(s.getId(), sectionId)).findAny();
        if(any.isPresent()){
            return any.get();
        }
        return null;
    }

    @Override
    public void addQuestions(QuestionFormDTO dto) {
        InteractionQuestion question = BeanUtils.copyBean(dto, InteractionQuestion.class);
        question.setUserId(UserContext.getUser());
        question.setCreateTime(LocalDateTime.now());
        question.setUpdateTime(LocalDateTime.now());
        this.save(question);
    }


    @Override
    public QuestionVO queryQuestionById(Long id) {
        InteractionQuestion question = this.getById(id);
        AssertUtils.isNotNull(question, "问题不存在");
        QuestionVO vo = BeanUtils.copyBean(question, QuestionVO.class);
        // 如果不是匿名 feign查询用户信息
        if(question.getAnonymity() !=null && !question.getAnonymity()){
            UserDTO user = userClient.queryUserById(question.getUserId());
            vo.setUserName(user == null? null : user.getName());
            vo.setUserIcon(user == null ? null : user.getIcon());
        }
        return vo;
    }

    @Override
    public PageDTO<QuestionVO> pageQuery(QuestionPageQuery query) {
        // 获取用户id
        Long userId = UserContext.getUser();
        //设置分页条件
        Page<InteractionQuestion> ipage = query.toMpPageDefaultSortByCreateTimeDesc();
        //设置查询条件
        LambdaQueryWrapper<InteractionQuestion> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(query.getCourseId()!=null,InteractionQuestion::getCourseId,query.getCourseId() )
                .eq(query.getSectionId()!=null, InteractionQuestion::getSectionId, query.getSectionId())
                .eq(query.getOnlyMine()!=null && query.getOnlyMine(), InteractionQuestion::getUserId, userId)
                .eq(InteractionQuestion::getHidden, false);
        //分页查询
        Page<InteractionQuestion> page = this.page(ipage, queryWrapper);
        List<InteractionQuestion> questions = page.getRecords();
        if(CollectionUtils.isEmpty(questions)){
            return PageDTO.empty(ipage);
        }
        // 接下来要干的事情：把数据库中的question 转化成 前端页面需要的 VO
//        List<QuestionVO> voList = new ArrayList<>();
//        for (InteractionQuestion question : questions) {
//            QuestionVO vo = BeanUtils.copyBean(question, QuestionVO.class);
//            // 如果不是匿名
//            if(question.getAnonymity() != null && !question.getAnonymity()){
//                // feign调用查询 userName 和 userIcon
//                UserDTO userDTO = userClient.queryUserById(question.getUserId());
//                vo.setUserName(userDTO==null?null:userDTO.getName());
//                vo.setUserIcon(userDTO==null?null:userDTO.getIcon());
//            }
//            // 查询最新的回复
//            if(question.getLatestAnswerId() != null){
//                InteractionReply answer = replyService.getById(question.getLatestAnswerId());
//                AssertUtils.isNotNull(answer, "answer不能为空");
//                vo.setLatestReplyContent(answer.getContent());
//                // 只有answer不是匿名的时候
//                if(answer.getAnonymity()!=null && !answer.getAnonymity()){
//                    Long answerUserId = answer.getUserId();
//                    UserDTO userDTO = userClient.queryUserById(answerUserId);
//                    vo.setLatestReplyUser(userDTO==null?null:userDTO.getName());
//                }
//            }
//            voList.add(vo);
//        }
//        return PageDTO.of(ipage, voList);

        // 20次feign调用 + 10次数据库
        // 1次feign调用（查询用户） + 1次数据库查询（查answer）

        List<InteractionReply> answers = null;
        // 拿到所有的userId去查询userName，userId由2部分组成，一部分是question的userId 另一部分是answer的userId
        Set<Long> userIds = new HashSet<>();

        // 拿到question中的userId
        List<Long> questionUserId = questions.stream().filter(q->q.getAnonymity()!=null && !q.getAnonymity())
                .map(q -> q.getUserId()).distinct().collect(Collectors.toList());
        userIds.addAll(questionUserId);

        //    找到所有的answerId
        List<Long> answerIds = questions.stream()
                .filter(q -> q.getLatestAnswerId() != null)
                .map(InteractionQuestion::getLatestAnswerId)
                .collect(Collectors.toList());
        if(!CollectionUtils.isEmpty(answerIds)){
            // 查询answer信息，1次数据库的查询就拿到了所有的answer
            answers = replyService.listByIds(answerIds);
            if(!CollectionUtils.isEmpty(answers)){
                // 得到不是匿名的answer的userId
                List<Long> answerUserIds = answers.stream().filter(a->a.getAnonymity()!=null && !a.getAnonymity()).map(a -> a.getUserId()).distinct().collect(Collectors.toList());
                userIds.addAll(answerUserIds);
            }
        }

        // 远程调用feign接口 查询用户信息， 1次feign远程调用
        List<UserDTO> userList = userClient.queryUserByIds(userIds);
        // 封装结果对象
        List<QuestionVO>  voList = new ArrayList<>();
        // question 转化成  vo
        for (InteractionQuestion question : questions) {
            QuestionVO vo = BeanUtils.copyBean(question, QuestionVO.class);
            // 如果问题不是匿名的，就需要查询提问者的userName和userIcon
            if(question.getAnonymity() != null && !question.getAnonymity()){
                UserDTO user = findUser(userList, question.getUserId());
                vo.setUserName(user==null?null:user.getName());
                vo.setUserIcon(user==null?null:user.getIcon());
            }
            InteractionReply answer = findAnswer(answers,question.getLatestAnswerId());
            vo.setLatestReplyContent(answer==null?null:answer.getContent());
            // 如果answer不是匿名的，就填充answer的userName
            if(answer !=null && answer.getAnonymity() != null && !answer.getAnonymity()){
                UserDTO user = findUser(userList, answer.getUserId());
                vo.setLatestReplyUser(user==null?null:user.getName());
            }
            voList.add(vo);
        }
        return PageDTO.of(ipage, voList);
    }

    private InteractionReply findAnswer(List<InteractionReply> answers, Long answerId) {
        if(answerId == null || CollectionUtils.isEmpty(answers)){
            return null;
        }
        Optional<InteractionReply> any = answers.stream().filter(a -> Objects.equals(a.getId(), answerId)).findAny();
        if(any.isPresent()){
            return any.get();
        }
        return null;
    }

    private UserDTO findUser(List<UserDTO> userList, Long userId) {
        Optional<UserDTO> any = userList.stream().filter(u -> Objects.equals(u.getId(), userId)).findAny();
        if(any.isPresent()){
            return any.get();
        }
        return null;
    }
}
